#pragma once

#include "GpioCommon.h"

extern "C"
{
    // GpioInit
    // Must be called before anything else
    // ret: FALSE on error (GetLastError() will return error code)
    BOOL GpioInit();

    // GpioDeinit
    // Must be called when GPIO is no longer needed (cleans up handles etc)
    // ret: FALSE on error (GetLastError() will return error code)
    BOOL GpioDeinit();

    // GPIO_CONFIG
    // -----------
    // Port         : GPIO Port
    //                - GPIO_PORT_1
    //                - GPIO_PORT_2
    //                - GPIO_PORT_3
    //                - GPIO_PORT_4
    // Pin          : GPIO Pin
    //                - GPIO_PIN_0
    //                - GPIO_PIN_1
    //                - ...
    //                - GPIO_PIN_30
    //                - GPIO_PIN_31
    // Function     : GPIO Function (READ ONLY)
    //                - GPIO_FUNCTION_ALT0
    //                - GPIO_FUNCTION_ALT1
    //                - ...
    //                - GPIO_FUNCTION_ALT6
    //                - GPIO_FUNCTION_ALT7
    // Direction    : GPIO Direction
    //                - GPIO_DIR_IN
    //                - GPIO_DIR_OUT
    // Interrupt    : GPIO Interrupt Configuration
    //                - GPIO_INTR_LOW_LEV
    //                - GPIO_INTR_HIGH_LEV
    //                - GPIO_INTR_RISE_EDGE
    //                - GPIO_INTR_FALL_EDGE
    //                - GPIO_INTR_BOTH_EDGE
    //                - GPIO_INTR_NONE
    // Loopback     : GPIO Loopback mode
    //                - GPIO_LOOPBACK_DISABLE
    //                - GPIO_LOOPBACK_ENABLE
    //                - GPIO_LOOPBACK_INVALID
    // Slew         : GPIO Slew rate
    //                - GPIO_SLEW_SLOW
    //                - GPIO_SLEW_FAST
    //                - GPIO_SLEW_INVALID
    // Drive        : GPIO Drive Strength
    //                - GPIO_DRIVE_NORMAL
    //                - GPIO_DRIVE_HIGH
    //                - GPIO_DRIVE_MAX
    //                - GPIO_DRIVE_INVALID
    // OpenDrain    : GPIO Open Drain mode
    //                - GPIO_OPENDRAIN_DISABLE
    //                - GPIO_OPENDRAIN_ENABLE
    //                - GPIO_OPENDRAIN_INVALID
    // Pull         : GPIO Pull up/pull down/keep Configuration
    //                - GPIO_PULL_NONE
    //                - GPIO_PULL_KEEPER
    //                - GPIO_PULL_DOWN_100K
    //                - GPIO_PULL_UP_47K
    //                - GPIO_PULL_UP_100K
    //                - GPIO_PULL_UP_22K
    //                - GPIO_PULL_INVALID
    // Hysteresis   : GPIO Hysteresis mode
    //                - GPIO_HYSTERESIS_DISABLE
    //                - GPIO_HYSTERESIS_ENABLE
    //                - GPIO_HYSTERESIS_INVALID
    // Voltage      : GPIO Voltage
    //                - GPIO_VOLTAGE_3V3
    //                - GPIO_VOLTAGE_1V8
    //                - GPIO_VOLTAGE_INVALID

    // GpioGetConfig
    // Gets the current GPIO configuration
    // in : Port, Pin
    // out: All other GPIO_CONFIG members
    //      Note: GPIO_CONFIG members set to GPIO_XXX_INVALID indicate that field
    //            is not configurable for the specified GPIO. See appendix A in the
    //            Freescale i.MX25 Reference Manual
    // ret: FALSE on error (GetLastError() will return error code)
    BOOL GpioGetConfig(LPGPIO_CONFIG pGpioConfig);

    // GpioSetConfig
    // Sets the current GPIO configuration
    // in : GPIO_CONFIG members set to desired configuration
    //      Member 'Function' is ignored (will always be set to the 'GPIO' function)
    // out: Configuration as read back after setting it (this can be different than what you expect
    //      because not all PADs support all configurations; see 4.7.2 in the iMX25 Reference Manual)
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will return FALSE with GetLastError() ERROR_ACCESS_DENIED if the GPIO is not 'safe'
    // to set as specified by the Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
    BOOL GpioSetConfig(LPGPIO_CONFIG pGpioConfig);

    // GPIO for Pin Functions
    // ----------------------
    // Port         : GPIO Port
    //                - GPIO_PORT_1
    //                - GPIO_PORT_2
    //                - GPIO_PORT_3
    //                - GPIO_PORT_4
    // Pin          : GPIO Pin
    //                - GPIO_PIN_0
    //                - GPIO_PIN_1
    //                - ...
    //                - GPIO_PIN_30
    //                - GPIO_PIN_31
    // Value        : in/out depending on function

    // GPIO for Port Functions
    // ----------------------
    // Port         : GPIO Port
    //                - GPIO_PORT_1
    //                - GPIO_PORT_2
    //                - GPIO_PORT_3
    //                - GPIO_PORT_4
    // Mask         : 32 bit GPIO Pin Mask
    // Value        : in/out depending on function

    // GpioReadPin
    // Reads the GPIO pin value
    // in : Port, Pin
    // out: Value (1 or 0)
    // ret: FALSE on error (GetLastError() will return error code)
    BOOL GpioReadPin(LPGPIO pGpio);

    // GpioWritePin
    // Sets the GPIO pin value
    // in : Port, Pin
    // out: Value (1 or 0)
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will return FALSE with GetLastError() ERROR_ACCESS_DENIED if the GPIO is not 'safe'
    // to set as specified by the Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
    BOOL GpioWritePin(LPGPIO pGpio);

    // GpioReadPort
    // Reads multiple GPIO pins on the same port
    // in : Port, Mask
    // out: Value
    // ret: FALSE on error (GetLastError() will return error code)
    BOOL GpioReadPort(LPGPIO pGpio);

    // GpioWritePort
    // Sets multiple GPIO pins on the same port
    // in : Port, Mask
    // out: Value
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will adjust (and return) the Mask according to the 'safe' mask as specified by the 
    // Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO] and will return FALSE with 
    // GetLastError() ERROR_ACCESS_DENIED if the Mask is 0 (no GPIO's could be safely written)
    BOOL GpioWritePort(LPGPIO pGpio);

    // GpioReadIntrPin
    // Reads the interrupt status of the GPIO pin
    // in : Port, Mask
    // out: Value
    // ret: FALSE on error (GetLastError() will return error code)
    BOOL GpioReadIntrPin(LPGPIO pGpio);

    // GpioReadIntrPort
    // Reads the interrupt status of multiple GPIO pins on the same port
    // in : Port, Mask
    // out: Value
    // ret: FALSE on error (GetLastError() will return error code)
    BOOL GpioReadIntrPort(LPGPIO pGpio);

    // GpioClearIntrPin
    // Clears the interrupt of the GPIO pin
    // in : Port, Mask
    // out: Value
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will return FALSE with GetLastError() ERROR_ACCESS_DENIED if the GPIO is not 'safe'
    // to set as specified by the Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
    BOOL GpioClearIntrPin(LPGPIO pGpio);

    // GpioClearIntrPort
    // Clears the interrupt of multiple GPIO pins on the same port
    // in : Port, Mask
    // out: Value
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will adjust (and return) the Mask according to the 'safe' mask as specified by the 
    // Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO] and will return FALSE with 
    // GetLastError() ERROR_ACCESS_DENIED if the Mask is 0 (no GPIO's could be safely written)
    BOOL GpioClearIntrPort(LPGPIO pGpio);

    // GpioRegisterEvent
    // Registers an event to be signaled when the GPIO pin generates an interrupt
    // in : Port, Pin, Event name
    // out: N/A
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will return FALSE with GetLastError() ERROR_ACCESS_DENIED if the GPIO is not 'safe'
    // to set as specified by the Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
    BOOL GpioRegisterEvent(LPGPIO_EVENT pGpioEvent);

    // GpioDeregisterEvent
    // Deregisters a previously registered event on a GPIO pin
    // in : Port, Pin
    // out: N/A
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will return FALSE with GetLastError() ERROR_ACCESS_DENIED if the GPIO is not 'safe'
    // to set as specified by the Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
    BOOL GpioDeregisterEvent(LPGPIO_EVENT pGpioEvent);

    // GpioGetEvent
    // Returns the name of a registered event on a GPIO pin (if any)
    // in : Port, Pin and an allocated buffer of MAX_PATH WCHARs in pszEvent
    // out: Event name
    // ret: FALSE on error (GetLastError() will return error code)
    //
    // This function will return FALSE with GetLastError() ERROR_ACCESS_DENIED if the GPIO is not 'safe'
    // to set as specified by the Port1...Port4 values in [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
    BOOL GpioGetEvent(LPGPIO_EVENT pGpioEvent);
}